// 动态规划 - 核心 5 步：
// 1. 确定状态表示 - 根据 题目要求，经验(以 i,j 位置为结尾/开始......)，发现重复子问题 确定状态表示
// 2. 推导状态转移方程: dp[i] = ?
//    用 之前的状态 或者 之后的状态 推导当前的状态（根据最近一步划分问题）
// 3. 初始化：保证填表时不越界，结合多开数组的技巧
// 4. 确定填表顺序：填写当前状态值的时候，所需状态的值已经计算过了
// 5. 返回值：结合题目要求 + 状态表示

// 技巧：
// 01 背包问题：使用滚动数组进行优化，删除横坐标，从右往左填表
// 完全背包问题：使用滚动数组进行优化，删除横坐标，从左往右填表

// 例题 7:
// 给你一个整数数组 coins 表示不同面额的硬币，另给一个整数 amount 表示总金额。
//
//        请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额，返回 0 。
//
//        假设每一种面额的硬币有无限个。
//
//        题目数据保证结果符合 32 位带符号整数。
//
//        示例 1：
//
//        输入：amount = 5, coins = [1, 2, 5]
//        输出：4
//        解释：有四种方式可以凑成总金额：
//        5=5
//        5=2+2+1
//        5=2+1+1+1
//        5=1+1+1+1+1
//        示例 2：
//
//        输入：amount = 3, coins = [2]
//        输出：0
//        解释：只用面额 2 的硬币不能凑成总金额 3 。
//        示例 3：
//
//        输入：amount = 10, coins = [10]
//        输出：1
//
//
//        提示：
//
//        1 <= coins.length <= 300
//        1 <= coins[i] <= 5000
//        coins 中的所有值 互不相同
//        0 <= amount <= 5000

// 解题思路:
// dp[i][j] 表示从 [0, i] 区间内选取硬币，金额正好等于 j 的选法数
// 初始化：dp[0][0] = 0
// 根据最后一个硬币分情况讨论：
// 不选 i 位置的硬币: dp[i][j] = dp[i - 1][j]
// 选 i 位置的硬币: dp[i][j] = dp[i][j - coins[i]]
// 选取两种情况下的和

public class Change {

}
